<template>
  <div class="historyMsgBox" ref="historyMsgBox">

    <TipMsg ref="tipMsg"></TipMsg>

    <div class="header">
      <span @click="goBack" class="goBack"> &lt;&nbsp;返回 </span>
      <div class="name">{{selectUser}}</div>
    </div>

    <div class="msgBox">

      <div class="getMoreMsg" @click="getMoreMsg">{{hasMoreMsg ? '点击，加载更多聊天消息' : '已无更多聊天消息'}}</div>

      <div :class="[item.bySelf ? 'myMsg' : 'otherMsg']"  v-for="(item,index) in newHistoryMessage" :key="item+index">

        <div class="msg " v-if="item.msg && !item.type">
          <!-- 聊天消息 -->
          <span
            v-html="renderTxt(item.msg)"
          />
        </div>

        <!-- 文件 -->
        <div class="fileMsg" v-if="item.type === 'file'">
          <div>
            <div class="title">文件</div>

            <div class="filename">{{item.filename}}</div>

            <a :href="item.msg" :download="item.filename"  target="tempiframe">点击下载</a>
            <iframe name="tempiframe" style="display:none;"></iframe>

            <span class="filelength">{{item.file_length | readablizeBytes}}</span>
          </div>
        </div>

        <!-- 图片 -->
        <div class="imgMsg" v-if="item.type === 'img'">
          <img :src="item.msg" alt="图片加载失败!">
        </div>


        <div class="timeBox">
          <span>{{item.time | renderTime}}</span>
          <span v-if="item.status === 'read' && item.bySelf">已读</span>
          <span v-if="item.status === 'sending' && item.bySelf">已发送</span>
        </div>
      </div>

    </div>


    <div class="footer">

      <div class="iconfontBox">
        <!-- 表情-->
        <ChatEmoji v-on:selectEmoji="selectEmoji" ref="chatemoji" :sendTextMsg="sendTextMsg"></ChatEmoji>

        <div class="uploadFileBox">
          <span class="iconfont icon-wj-fswj"></span>
          <input type="file" @change="inputUploadFile" ref="fileDom">
        </div>

        <div class="uploadImgBox">
          <span class="iconfont icon-tupian"></span>
          <input type="file" @change="inputUploadImg" ref="imgDom">
        </div>

        <span class="iconfont icon-smiling" @click="showEmojiBox"></span>

        <div class="fasong" @click="onSendTextMsg">发送消息</div>
      </div>


      <textarea type="text" placeholder="点击输入聊天消息" v-model="sendTextMsg"></textarea>

    </div>

  </div>
</template>

<script>
import emoji from "../config/emoji";
import ChatEmoji from "./chatEmoji";
import TipMsg from "./tipMsg";
import moment from 'moment';
import {mapMutations, mapState} from 'vuex';

export default {
  name: "chatContent",
  components: {
    ChatEmoji,
    TipMsg
  },
  data(){
    return {
      historyMessages: [],    // 聊天数据
      hasMoreMsg: true,    // 是否展示更多
      isShowEmojiBox: false,   // 是否展示表情框
      sendTextMsg: '',    // 将要发送的文本内容
      selectUser: '',
      timeId: null, // 定时器
    }
  },

  computed: {
    ...mapState({
      receiveMsgList: state => state.chat.receiveMsgList,
      chatId: state => state.chat.chatIdList,  // 聊天对象id
    }),


    newHistoryMessage(){
      let newArr = this.historyMessages;

      newArr.push(...this.receiveMsgList);
      this.deleteReadMsg();
      return newArr
    }
  },


  filters: {
    renderTime: function (time) {
      if ( typeof time === 'string' ) {
        time = parseInt(time)
      }
      return moment(time).format('MM-DD HH:mm');
    },

    readablizeBytes(value) {
      let s = ["Bytes", "KB", "MB", "GB", "TB", "PB"];
      let e = Math.floor(Math.log(value) / Math.log(1024));
      return (value / Math.pow(1024, Math.floor(e))).toFixed(2) + " " + s[e];
    },
  },


  destroyed() {
    this.deleteReadMsg();
  },

  methods: {
    ...mapMutations({
      deleteReadMsg: 'deleteReadMsg'
    }),

    initHander(){
      this.selectUser = this.chatId.name;

      this.historyMessages = [];
      this.isShowEmojiBox = false;
      this.sendTextMsg = '';
      this.hasMoreMsg = true;


      this.getHistoryMessage(-1)

      this.deleteReadMsg();

      // 消息自动滚动到底部
      let that = this;
      clearTimeout(this.timeId);
      this.timeId = null;
      this.timeId = setTimeout(function (){
        that.scrollToBottom();
        clearTimeout(that.timeId)
      }, 500)
    },


    // 返回
    goBack(){
      this.clientWidth = document.body.clientWidth
      if (this.clientWidth < 500) {
        this.$emit('goBack')
      }
    },

    // 滚动到底部
    scrollToBottom(){
      this.$nextTick(()=>{
        let box = this.$refs.historyMsgBox

        if (box) {
          box.scrollTop = box.scrollHeight
        }
      })
    },

    // 点击上传图片
    inputUploadFile(e){
      let file = WebIM.utils.getFileUrl(e.target);
      if(!file.filename){
        this.$refs.tipMsg.showTipMsg('未获取到文件，请重新上传文件');
        this.$refs.fileDom.value = null;
        return false;
      }

      let obj = {
        chatType: 'contact',
        chatId: this.chatId,
        file: file,
        roomType: false,
        callback: () => {
          this.$refs.fileDom.value = null;
        }
      };
      this.sendFileMessage(obj);
    },

    // 发送文件
    sendFileMessage(payload){
      const { chatType, chatId, roomType, file, callback } = payload;
      const id = WebIM.conn.getUniqueId();
      const jid = {
        contact: "name",
        group: "groupid",
        chatroom: "id"
      };
      const that = this;
      const msgObj = new WebIM.message("file", id);
      msgObj.set({
        file: file,
        ext: {
          file_length: file.data.size
        },
        to: chatId[jid[chatType]],
        chatType: chatType,
        roomType: roomType,
        onFileUploadError: function (error) {
          console.log("文件上传失败", error);
          that.$refs.tipMsg.showTipMsg('文件上传失败')
          callback();
        },
        onFileUploadComplete: function (data) {
          let url = data.uri + "/" + data.entities[0].uuid;
          that.updateMsgList({
            msg: url,
            chatType,
            chatId: chatId[jid[chatType]],
            bySelf: true,
            type: "file",
            filename: file.data.name,
            file_length: file.data.size,
            time: data.timestamp,
            mid: id,
            status: "sending"
          });
          callback();
        },
        success: function () {
          that.$refs.tipMsg.showTipMsg('文件上传成功')
        }
      });
      WebIM.conn.send(msgObj.body);
    },

    // 点击上传图片
    inputUploadImg(e){
      let file = WebIM.utils.getFileUrl(e.target);

      if (!file.filename) {
        this.$refs.tipMsg.showTipMsg('未获取到图片，请重新上传图片');
        this.$refs.imgDom.value = null;
        return false;
      }

      let filetypeArr = ['png', 'jpg', 'jpeg', 'gif']
      let filetype = file.filetype.toLowerCase();
      let index = filetypeArr.findIndex(item => filetype === item)
      if (index === -1) {
        this.$refs.tipMsg.showTipMsg(`
          <h4>文件类型不支持</h4>
          <div>请上传
            <span style="color: red">png</span>,
            <span style="color: red">jpg</span>,
            <span style="color: red">jpeg</span>,
            <span style="color: red">gif</span>图片
          </div>
        `);
        this.$refs.imgDom.value = null;
        return;
      }

      let obj = {
        chatType: 'contact',
        chatId: this.chatId,
        file: file,
        roomType: false,
        callback: () => {
          this.$refs.imgDom.value = null;
        }
      };

      this.sendImgMessage(obj);
    },

    // 发送图片
    sendImgMessage: function (payload) {
      const { chatType, chatId, roomType, file, callback } = payload;
      const id = WebIM.conn.getUniqueId();
      const jid = {
        contact: "name",
        group: "groupid",
        chatroom: "id"
      };
      const that = this;

      const msgObj = new WebIM.message("img", id);

      msgObj.set({
        file: file,
        to: chatId[jid[chatType]],
        chatType: chatType,
        roomType: roomType,
        onFileUploadError: function (error) {
          console.log('error', error)
          that.$refs.tipMsg.showTipMsg('上传图片失败');
          callback();
        },
        onFileUploadComplete: function (data) {
          let url = data.uri + "/" + data.entities[0].uuid;
          that.updateMsgList({
            msg: url,
            chatType,
            chatId: chatId[jid[chatType]],
            bySelf: true,
            type: "img",
            time: data.timestamp,
            mid: id,
            status: "sending"
          });
          callback();
        },
        success: function (res) {
          console.log('res', res)
          that.$refs.tipMsg.showTipMsg('上传图片成功');
        }
      });
      WebIM.conn.send(msgObj.body);
    },

    // 发送消息、图片、文件后，更新聊天内容列表
    updateMsgList(data){
      this.historyMessages.push(data)

      this.scrollToBottom()
    },


    customEmoji(value) {
      return `<img src="../../../static/faces/${value}" style="width: 20px"/>`;
    },

    // TODO 这是环信的写法，最好研究一下不用v-html显示图片
    // 聊天消息，正则匹配表情
    renderTxt(txt = "") {
      let rnTxt = [];
      let match = null;
      const regex = /(\[.*?\])/g;
      let start = 0;
      let index = 0;

      txt = txt.replace(/</g, '&lt;')
      txt = txt.replace(/>/g, '&gt;')

      while ((match = regex.exec(txt))) {
        index = match.index;
        if (index > start) {
          rnTxt.push(txt.substring(start, index));
        }
        if (match[1] in emoji.obj) {
          const v = emoji.obj[match[1]];
          rnTxt.push(this.customEmoji(v));
        } else {
          rnTxt.push(match[1]);
        }
        start = index + match[1].length;
      }
      rnTxt.push(txt.substring(start, txt.length));

      return rnTxt.toString().replace(/,/g, "");
    },

    // 显示隐藏表情框
    showEmojiBox(){
      let isShowEmojiBox = this.$refs.chatemoji.isShowEmojiBox;
      if (isShowEmojiBox) {
        this.$refs.chatemoji.isShowEmojiBox = false
      } else {
        this.$refs.chatemoji.isShowEmojiBox = true
      }
    },

    // 点击发送，向环信发送消息
    onSendTextMsg(){
      this.sendTextMsg = this.sendTextMsg.trim();
      if (this.sendTextMsg.length === 0) {
        that.$refs.tipMsg.showTipMsg('不能上传空消息');
        return
      }

      this.onSendText({
        chatType: 'contact',
        chatId: this.chatId,
        message: this.sendTextMsg,
      });
      this.sendTextMsg = "";
    },

    // 向环信发送消息
    onSendText: function (payload) {
      const { chatType, chatId, message } = payload;
      const id = WebIM.conn.getUniqueId();
      const time = new Date();
      const chatroom = chatType === "chatroom";
      const type = chatType === "contact" ? "singleChat" : "groupChat";
      const jid = {
        contact: "name",
        group: "groupid",
        chatroom: "id"
      };
      const that = this;

      const msgObj = new WebIM.message("txt", id);
      msgObj.set({
        msg: message,
        to: chatId[jid[chatType]],
        chatType: type,
        roomType: chatroom,
        success: function () {
          that.updateMsgList({
            chatType,
            chatId: chatId[jid[chatType]],
            msg: message,
            bySelf: true,
            time: time,
            mid: id,
            status: "sending"
          });
          that.scrollToBottom()
        },
        fail: function (e) {
          that.$refs.tipMsg.showTipMsg('消息发送失败');
        }
      });

      WebIM.conn.send(msgObj.body);
    },

    // 将选择的表情添加到聊天内容中
    selectEmoji(newSendTextMsg){
      this.sendTextMsg = newSendTextMsg;
    },

    // 获取更多聊天消息
    getMoreMsg(){
      let startId = -1;
      if (this.historyMessages.length > 0){
        startId = this.historyMessages[this.historyMessages.length - 1].mid;
      }

      this.getHistoryMessage(startId)
    },

    // 获取聊天内容
    getHistoryMessage(startId = -1) {
      if (!this.hasMoreMsg) {
        return
      }

      let {selectUser} = this;

      let that = this;
      let historyMsg = [];

      let payload = {
        name: selectUser,
        isGroup: false
      };

      if (startId === -1) {
        WebIM.conn.mr_cache = []
      }

      const options = {
        queue: payload.name,
        isGroup: payload.isGroup,
        count: 10,  // 每次获取消息条数
        start: startId,
        success: function (msgs) {

          console.log('是否获取了聊天数据 msgs', msgs)

          if (msgs.length === 0){
            that.hasMoreMsg = false;
            return
          }

          try {
            payload.success && payload.success(msgs);
            if (msgs.length) {
              const userInfo = JSON.parse(localStorage.getItem("userInfo"));
              const userId = userInfo && userInfo.userId;
              msgs.forEach((item) => {
                let time = Number(item.time);
                let msg = {};
                const bySelf = item.from == userId;
                if (!item.filename) {
                  msg = {
                    chatType: payload.isGroup ? "group" : "contact",
                    chatId: bySelf ? item.to : item.from,
                    msg: item.data,
                    bySelf: bySelf,
                    time: time,
                    mid: item.id,
                    status: "read"
                  };
                  if (payload.isGroup) {
                    msg.chatId = item.to;
                  }
                  else {
                    msg.chatId = bySelf ? item.to : item.from;
                  }
                }
                else if (!item.ext.file_length && item.filename !== "audio" && item.filename.substring(item.filename.length - 3) !== "mp4") { // 为图片的情况
                  msg = {
                    msg: item.url,
                    chatType: payload.isGroup ? "group" : "contact",
                    chatId: bySelf ? item.to : item.from,
                    bySelf: bySelf,
                    type: "img",
                    time: time,
                    mid: item.id,
                    status: "read"
                  };
                  if (payload.isGroup) {
                    msg.chatId = item.to;
                  }
                  else {
                    msg.chatId = bySelf ? item.to : item.from;
                  }
                }
                else if (item.filename === "audio") {
                  msg = {
                    msg: item.url,
                    chatType: payload.isGroup ? "group" : "contact",
                    chatId: bySelf ? item.to : item.from,
                    bySelf: bySelf,
                    type: "audio",
                    time: time,
                    mid: item.id,
                    status: "read"
                  };
                  if (payload.isGroup) {
                    msg.chatId = item.to;
                  }
                  else {
                    msg.chatId = bySelf ? item.to : item.from;
                  }
                }
                else if (item.filename.substring(item.filename.length - 3) === "mp4") {
                  msg = {
                    msg: item.url,
                    chatType: payload.isGroup ? "group" : "contact",
                    chatId: bySelf ? item.to : item.from,
                    bySelf: bySelf,
                    type: "video"
                  };
                  if (payload.isGroup) {
                    msg.chatId = item.to;
                  }
                  else {
                    msg.chatId = bySelf ? item.to : item.from;
                  }
                }
                else {
                  msg = {
                    msg: item.url,
                    chatType: payload.isGroup ? "group" : "contact",
                    chatId: bySelf ? item.to : item.from,
                    bySelf: bySelf,
                    type: "file",
                    filename: item.filename,
                    file_length: item.file_length,
                    time: time,
                    mid: item.id,
                    status: "read"
                  };
                  if (payload.isGroup) {
                    msg.chatId = item.to;
                  }
                  else {
                    msg.chatId = bySelf ? item.to : item.from;
                  }
                }
                msg.isHistory = true;

                historyMsg.push(msg)
              });
            }

            that.historyMessages.unshift(...historyMsg);
          }
          catch (e) {
            console.log("error", e);
          }
        },
        fail: function () { }
      };
      WebIM.conn.fetchHistoryMessages(options);
    },
  }
}
</script>

<style scoped lang="less">
.historyMsgBox{
  font-size: 4vw;
  width: 100%;
  height: 100vh;
  overflow-y: auto;

  .header{
    position: fixed;
    top: 0;
    left: 300px;
    right: 0;
    height: 16vw;
    line-height: 16vw;
    text-align: center;
    border-bottom: 1px solid #eee;
    background-color: #fafafa;
    box-sizing: border-box;

    .goBack{
      display: inline-block;
      padding: 0 3vw;
      position: absolute;
      left: 0;
      top: 0;
    }
  }

  .msgBox{
    width: 100%;
    box-sizing: border-box!important;
    padding: 16vw 0 31vw 0;
    overflow: hidden;

    .getMoreMsg{
      background-color: #eee;
      height: 10vw;
      line-height: 10vw;
      color: #226ebc;
      text-align: center;
      width: 80%;
      margin: 1vw auto;
      border-radius: 100px;
    }

    .otherMsg, .myMsg{
      padding: 3vw 5vw;

      >.msg{
        width: 100%;
        overflow: hidden;
        >span{
          min-width: 50%;
          max-width: 100%;
          padding: 3vw;
          box-sizing: border-box;
          border: 1px solid #eee;
          border-radius: 100vw;
        }
      }
      >.fileMsg{
        width: 100%;
        >div{
          border: 1px solid #eee;
          box-shadow: 0 0 10px #999;
          overflow: hidden;
          .title{
            font-size: 6vw;
            padding: 3vw 3vw 0 3vw;
            border-bottom: 1px solid #eee;
          }
          .filename{
            font-weight: 900;
            padding: 3vw;
            color: #000;
          }
          >a{
            float: right;
            margin: 4vw 3vw 4vw 4vw;
            color: #aaa;
            text-decoration:none;
          }
          >span{
            float: right;
            margin: 4vw 3vw 4vw 4vw;
            color: #aaa;
          }
        }

      }
      >.imgMsg{
        overflow: hidden;
        >img{
          max-width: 100%;
        }
      }
      >.timeBox{
        margin-top: 1vw;
        font-size: 12px;
        color: #aaa
      }
    }

    .otherMsg{
      width: 50%;
      float: left;
      overflow: hidden;
      >.msg{
        overflow: hidden;
        >span{
          float: left;
        }
      }
      >.imgMsg{
        >img{
          float: left;
        }
      }
      >.timeBox{
        float: left;

      }
    }

    .myMsg{
      width: 50%;
      float: right;
      overflow: hidden;
      >.msg{
        overflow: hidden;
        >span{
          float: right;
        }
      }
      >.imgMsg{
        >img{
          float: right;
        }
      }
      >.timeBox{
        float: right;
      }
    }
  }


  .footer{
    //width: 100%;
    box-sizing: border-box;
    padding: 3vw;
    position: fixed;
    bottom: 0;
    left: 300px;
    right: 0;
    border-top: 1px solid #eee;
    background-color: #fafafa;


    .iconfontBox{
      width: 100%;
      border-bottom: 1px solid #eee;

      .iconfont{
        display: inline-block;
        font-size: 7vw;
        margin: 1vw 2vw 1vw 0;
      }

      .uploadFileBox, .uploadImgBox{
        display: inline-block;
        position: relative;
        >input{
          position: absolute;
          left: 0;
          top: 0;
          opacity: 0;
          height: 100%;
          width: 100%;
          filter: alpha(opacity=0);
        }
      }
      .fasong{
        float: right;
        background-color: #226ebc;
        color: #fff;
        padding: 1vw 3vw;
        border-radius: 5px;
      }
    }

    textarea{
      box-sizing: border-box;
      border: none;
      width: 100%;
      resize: none;
      background-color: #fafafa;
      padding: 2vw 1vw;
      height: 13vw;
      font-size: 14px;
    }
  }
}

@media(min-width: 500px){   // pc端

  .historyMsgBox{
    font-size: 16px;
    .header{
      height: 50px;
      line-height: 50px;
      .goBack{
        display: none;
      }
    }

    .msgBox{
      padding: 50px 0 180px 0;

      .getMoreMsg{
        height: 30px;
        line-height: 30px;
      }

      .otherMsg, .myMsg{
        padding: 10px 20px;
        >.msg{
          >span{
            padding: 10px;
            border-radius: 100px;
          }
        }

        >.fileMsg{
          >div{
            .title{
              font-size: 20px;
              padding: 5px 5px 0 5px;
            }
            .filename{
              font-size: 14px;
              padding: 10px;
            }
            >a{
              margin: 10px 10px 10px 20px;
            }
            >span{
              margin: 10px 10px 10px 20px;
            }
          }

        }

        >.timeBox{
          margin-top: 10px;
        }
      }
    }

    .footer{
      padding: 10px;
      .iconfontBox{
        .iconfont{
          font-size: 24px;
          margin: 5px 10px 5px 0;
        }

        .fasong{
          padding: 5px 10px;
        }
      }
      textarea{
        width: 100%;
        height: 100px;
        line-height: 30px;
        padding: 5px;
      }
    }
  }

}

@media(max-width: 500px){
  .historyMsgBox{
    .header{
      left: 0;
    }
    .footer {
      left: 0;
    }

  }
}

</style>
